package com.weiiew.backend.utils.listener;

import lombok.extern.slf4j.Slf4j;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyListener;
import org.jnativehook.mouse.NativeMouseInputListener;
import org.jnativehook.mouse.NativeMouseWheelListener;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @Description 管理Jnativehook库的监听器, 因为Jnativehook库无法在Springboot关闭时自动关闭
 * @Author 魏锴
 * @Date 2025/4/28
 */
@Slf4j
@Component
public class ListenerManager {
    private final Map<String, NativeKeyListener> keyListeners = new ConcurrentHashMap<>();
    private final Map<String, NativeMouseInputListener> mouseListeners = new ConcurrentHashMap<>();
    private final Map<String, NativeMouseWheelListener> mouseWheelListeners = new ConcurrentHashMap<>();
    private final Object hookLock = new Object();
    private final AtomicBoolean hookActive = new AtomicBoolean(false);

    // 初始化日志配置（避免JNativeHook的默认日志）
    static {
        Logger.getLogger(GlobalScreen.class.getPackage().getName()).setLevel(Level.OFF);
    }

    /**
     * 注册键盘监听器
     *
     * @param listenerId 监听器唯一标识
     * @param listener   监听器实例
     */
    public void registerKeyListener(String listenerId, NativeKeyListener listener) {
        synchronized (hookLock) {
            ensureHookRegistered();
            keyListeners.put(listenerId, listener);
            GlobalScreen.addNativeKeyListener(listener);
            log.debug("注册键盘监听器: {}", listenerId);
        }
    }

    /**
     * 注销键盘监听器
     *
     * @param listenerId 监听器唯一标识
     */
    public void unregisterKeyListener(String listenerId) {
        synchronized (hookLock) {
            NativeKeyListener listener = keyListeners.remove(listenerId);
            if (listener != null) {
                GlobalScreen.removeNativeKeyListener(listener);
                log.debug("注销键盘监听器: {}", listenerId);
            }
            if (keyListeners.isEmpty() && mouseListeners.isEmpty() && mouseWheelListeners.isEmpty()) {
                shutdownHook();
            }
        }
    }

    /**
     * 注册鼠标监听器
     *
     * @param listenerId 监听器唯一标识
     * @param listener   监听器实例
     */
    public void registerMouseListener(String listenerId, NativeMouseInputListener listener) {
        synchronized (hookLock) {
            ensureHookRegistered();
            mouseListeners.put(listenerId, listener);
            GlobalScreen.addNativeMouseListener(listener);
            GlobalScreen.addNativeMouseMotionListener(listener);
            log.debug("注册鼠标监听器: {}", listenerId);
        }
    }

    /**
     * 注销鼠标监听器
     *
     * @param listenerId 监听器唯一标识
     */
    public void unregisterMouseListener(String listenerId) {
        synchronized (hookLock) {
            NativeMouseInputListener listener = mouseListeners.remove(listenerId);
            if (listener != null) {
                GlobalScreen.removeNativeMouseListener(listener);
                GlobalScreen.removeNativeMouseMotionListener(listener);
                log.debug("注销鼠标监听器: {}", listenerId);
            }
            if (keyListeners.isEmpty() && mouseListeners.isEmpty() && mouseWheelListeners.isEmpty()) {
                shutdownHook();
            }
        }
    }

    /**
     * 注册鼠标滚轮监听器
     *
     * @param listenerId 监听器唯一标识
     * @param listener   监听器实例
     */
    public void registerMouseWheelListener(String listenerId, NativeMouseWheelListener listener) {
        synchronized (hookLock) {
            ensureHookRegistered();
            mouseWheelListeners.put(listenerId, listener);
            GlobalScreen.addNativeMouseWheelListener(listener);
            log.debug("注册鼠标滚轮监听器: {}", listenerId);
        }
    }

    /**
     * 注销鼠标滚轮监听器
     *
     * @param listenerId 监听器唯一标识
     */
    public void unregisterMouseWheelListener(String listenerId) {
        synchronized (hookLock) {
            NativeMouseWheelListener listener = mouseWheelListeners.remove(listenerId);
            if (listener != null) {
                GlobalScreen.removeNativeMouseWheelListener(listener);
                log.debug("注销鼠标滚轮监听器: {}", listenerId);
            }
            if (keyListeners.isEmpty() && mouseListeners.isEmpty() && mouseWheelListeners.isEmpty()) {
                shutdownHook();
            }
        }
    }

    private void ensureHookRegistered() {
        if (!hookActive.get()) {
            try {
                GlobalScreen.registerNativeHook();
                hookActive.set(true);
                log.info("Jnativehook 全局钩子已激活");
            } catch (NativeHookException e) {
                throw new RuntimeException("钩子注册失败", e);
            }
        }
    }

    @PreDestroy
    private void shutdownHook() {
        synchronized (hookLock) {
            if (!hookActive.get()) return;
            try {
                keyListeners.keySet().forEach(this::unregisterKeyListener);
                mouseListeners.keySet().forEach(this::unregisterMouseListener);
                mouseWheelListeners.keySet().forEach(this::unregisterMouseWheelListener);
                GlobalScreen.unregisterNativeHook();
                hookActive.set(false);
                log.info("Jnativehook 全局钩子已关闭");
            } catch (NativeHookException e) {
                log.error("钩子注销异常: {}", e.getMessage());
            }
        }
    }
}